package com.spring;

import com.spring.AOP.AopAnnotation.Aspect;
import com.spring.springAnnotation.Bean;
import com.spring.springAnnotation.Component;
import com.spring.springAnnotation.Configuration;
import com.spring.springAnnotation.Scope;

import java.beans.Introspector;
import java.io.File;
import java.io.ObjectInputFilter;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


public class BeanDefinitionScanner {
    private final DefaultBeanFactory factory;

    public BeanDefinitionScanner(DefaultBeanFactory factory) {
        this.factory = factory;
    }
    public void scan(String path) {
// 扫描类路径，解析注解
        //转换
        path = path.replace(".", "/");
        //扫描
        //获取类加载器
        ClassLoader classLoader = LaiYaoApplicationContext.class.getClassLoader();
        //获取资源
        URL resource = classLoader.getResource(path);
        File file= new File(resource.getFile());
        if(file.isDirectory()) {
            File[] files = file.listFiles();
//2.1拿到所有的file
            for (File file1 : files) {
                //如果是类再截取
                if(file1.getName().endsWith(".class")){
                    //截取
                    String className = file1.getAbsolutePath();
                    className = className.substring(className.indexOf("com"), className.indexOf(".class"));
                    className = className.replace("\\", ".");
                    try {
                        Class<?> clazz = classLoader.loadClass(className);
//2.2判断是否是bean
                        if(clazz.isAnnotationPresent(Component.class)){
                            //说明这是bean
                            Component component = clazz.getAnnotation(Component.class);
                            String beanName = component.value();
                            //如果为空，设置默认值
                            if(beanName.equals("")){
                                beanName= Introspector.decapitalize(clazz.getSimpleName());
                            }
                            //3创建一个beanDefinition
                            DefaultBeanDefinition beanDefinition = new DefaultBeanDefinition();
                            beanDefinition.setBeanClass(clazz);
                            if(clazz.isAnnotationPresent(Scope.class)){
                                beanDefinition.setScope(clazz.getAnnotation(Scope.class).value());
                            }else{
                                beanDefinition.setScope("singleton");
                                beanDefinition.setBeanName(beanName);
                                factory.getRegistry().registerBeanDefinition(beanName, beanDefinition);
                            }
                            factory.getBeanDefinitionMap().put(beanName, beanDefinition);
                            //如果type查询池中没有，创建一个
                            HashMap<Class<?>, List<String>> typeMap = factory.getTypeMap();
                            if (!typeMap.containsKey(clazz)) {
                                typeMap.put(clazz, new ArrayList<>());
                            }else{
                                typeMap.get(clazz).add(beanName);
                            }
                            if (clazz.isAnnotationPresent(Configuration.class)) {
                                // 3.1 先注册配置类本身为Bean（可选，便于后续调用@Bean方法）
                                registerConfigurationBean(clazz);
                                // 3.2 解析@Bean方法，注册为BeanDefinition
                                registerBeanMethods(clazz);
                            }

//TODO：合并beanDefinition
                        }
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }

            }
        }

    }

    private void registerBeanMethods(Class<?> clazz) {
        // 获取配置类中所有public方法（@Bean方法通常是public）
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(Bean.class)) {
                Bean beanAnnotation = method.getAnnotation(Bean.class);
                // 1. 确定Bean名称（@Bean.value()优先，否则用方法名）
                String beanName = beanAnnotation.value().isEmpty()
                        ? method.getName()
                        : beanAnnotation.value();
                // 2. 创建BeanDefinition（Bean类型为方法返回值类型）
                Class<?> beanType = method.getReturnType();
                DefaultBeanDefinition definition = new DefaultBeanDefinition();
                definition.setBeanClass(beanType);
                definition.setScope("singleton"); // @Bean默认单例，可扩展支持@Scope
                definition.setBeanName(beanName);
                definition.setProperties("configClass", clazz);
                definition.setProperties("methodName", method);
                factory.getRegistry().registerBeanDefinition(beanName, definition);
            }
        }
    }

    private void registerConfigurationBean(Class<?> clazz) {
        String beanName = clazz.getAnnotation(Configuration.class).value();
        if(beanName.isEmpty()){
            beanName = clazz.getSimpleName();
            beanName = Introspector.decapitalize(beanName);
        }
        DefaultBeanDefinition definition = new DefaultBeanDefinition();
        definition.setBeanClass(clazz);
        definition.setScope("singleton"); // 配置类默认单例
        factory.getBeanDefinitionMap().put(beanName, definition);
    }
}
